from PyQt5 import QtCore, QtGui, QtWidgets
import json
import random

class Shader(object):
    def __init__(self) -> None:
        pass

    def insert_text(self,
                    textedit:QtWidgets.QPlainTextEdit, 
                    text:str,
                    fontsize:int,
                    fontcolor:QtGui.QColor,
                    backcolor:QtGui.QColor) -> None:
        fmt = QtGui.QTextCharFormat()
        fmt.setForeground(QtGui.QBrush(fontcolor))
        fmt.setBackground(QtGui.QBrush(backcolor))
        fmt.setFontPointSize(fontsize)
        textedit.mergeCurrentCharFormat(fmt)
        textedit.insertPlainText(text)

    def shader(self, textedit:QtWidgets.QPlainTextEdit,
               lines, config):
        macro = config.get('macro')
        r = macro.get('color').get('R')
        g = macro.get('color').get('G')
        b = macro.get('color').get('B')
        macro_color = QtGui.QColor(r, g, b)

        string = config.get('string')
        r = string.get('color').get('R')
        g = string.get('color').get('G')
        b = string.get('color').get('B')
        string_color = QtGui.QColor(r, g, b)

        note = config.get('note')
        r = note.get('color').get('R')
        g = note.get('color').get('G')
        b = note.get('color').get('B')
        note_color = QtGui.QColor(r, g, b)

        keywords = config.get('keywords')

        font_size = config.get('font_size')

        r = config.get('keyword_color').get('R')
        g = config.get('keyword_color').get('G')
        b = config.get('keyword_color').get('B')
        keyword_color = QtGui.QColor(r, g, b)

        r = config.get('default_color').get('R')
        g = config.get('default_color').get('G')
        b = config.get('default_color').get('B')
        default_color = QtGui.QColor(r, g, b)

        r = config.get('background_color').get('R')
        g = config.get('background_color').get('G')
        b = config.get('background_color').get('B')
        background_color = QtGui.QColor(r, g, b)

        multi_note_flag = False
        for line in lines:
            start = 0
            if multi_note_flag:
                if note.get('multiline')[1] in line:
                    index = line.find(note.get('multiline')[1], start)
                    self.insert_text(textedit, line[:index+len(note.get('multiline')[1])], font_size, note_color, background_color)
                    start = index + len(note.get('multiline')[1])
                    multi_note_flag = False
                else:
                    self.insert_text(textedit, line, font_size, note_color, background_color)
                    start = len(line)

            words = line[start:].split(' ')
            
            for word in words:
                word = word.strip()
                
                # 单行注释
                if note.get('single_row') in word:
                    index = line.find(note.get('single_row'), start)
                    self.insert_text(textedit, line[start:index], font_size, default_color, background_color)
                    self.insert_text(textedit, line[index:], font_size, note_color, background_color)
                    start = len(line)
                    break
                # 多行注释
                elif note.get('multiline')[0] in word:
                    index = line.find(note.get('multiline')[0], start)
                    end = line.find(note.get('multiline')[1], index+len(note.get('multiline')[0]))
                    if end >= 0:
                        self.insert_text(textedit, line[start:index], font_size, default_color, background_color)
                        self.insert_text(textedit, line[index:end+len(note.get('multiline')[1])], font_size, note_color, background_color)
                        start = end + len(note.get('multiline')[1])
                        continue
                    else:
                        self.insert_text(textedit, line[start:index], font_size, default_color, background_color)
                        self.insert_text(textedit, line[index:], font_size, note_color, background_color)
                        start = len(line)
                        multi_note_flag = True
                        break
                # 关键字
                elif word in keywords:
                    index = line.find(word, start)
                    if index >= start:
                        self.insert_text(textedit, line[start:index], font_size, default_color, background_color)
                        self.insert_text(textedit, word, font_size, keyword_color, background_color)
                        start = index + len(word)
                # 宏定义
                elif word in macro.get('keywords'):
                    index = line.find(word, start)
                    if index >= start:
                        self.insert_text(textedit, line[start:index], font_size, default_color, background_color)
                        self.insert_text(textedit, word, font_size, macro_color, background_color)
                        start = index + len(word)
                elif '(' in word:
                    sublist = word.split('(')
                    delchar = ['*', '&', ')']
                    for word in sublist:
                        for ch in delchar:
                            word = word.replace(ch, '')
                        word = word.strip ()
                        if word in keywords:
                            index = line.find(word, start)
                            self.insert_text(textedit, line[start:index], font_size, default_color, background_color)
                            self.insert_text(textedit, word, font_size, keyword_color, background_color)
                            start = index + len(word)
                # 字符串
                elif string.get('symbol') in word:
                    index = line.find(string.get('symbol'), start)
                    end = line.find(string.get('symbol'), index+1)
                    self.insert_text(textedit, line[start:index], font_size, default_color, background_color)
                    self.insert_text(textedit, line[index:end+1], font_size, string_color, background_color)
                    start = end+1
                else:
                    delchar = [';']
                    for ch in delchar:
                        word = word.replace(ch, '')
                    word = word.strip()
                    if word in keywords:
                        index = line.find(word, start)
                        self.insert_text(textedit, line[start:index], font_size, default_color, background_color)
                        self.insert_text(textedit, word, font_size, keyword_color, background_color)
                        start = index + len(word)

            self.insert_text(textedit, line[start:], font_size, default_color, background_color)

    def file_shader(self,
                    textedit:QtWidgets.QPlainTextEdit,
                    file:str,
                    json_file:str) -> None:
        '''
        根据json配置对输入的文件进行着色，显示到QPlainTextEdit控件中

        textedit: QPlainTextEdit控件对象
        file: 文件路径

        '''
        # 打开文件并按行读取文件内容
        with open(file, 'r') as f:
            lines = f.readlines()

        with open(json_file, 'r') as jf:
            config = json.load(jf)

        self.shader(textedit, lines, config)
